home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / GXToPostScript.cp next >
Encoding:
Text File  |  2000-09-28  |  19.9 KB  |  670 lines  |  [TEXT/CWIE]

  1. /*
  2.      File:        GXToPostScript.cp
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                      This file implements the Class for controling the GXToPostScript system.
  6.  
  7.      Version:    Technology:    Quickdraw GX 1.1.x
  8.       
  9.      Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  10. */
  11.  
  12. #include "GXExceptions.h"
  13. #include "GXtoPostScript.h"
  14. #include "GXExceptions.h"
  15. #include "PublicPostScriptIE.h"
  16. #include <GXFonts.h>
  17. #include "GXGraphicsPriv.h"
  18. #include "ProcessShape.h"
  19.  
  20. gxShape CGXToPSBuildShapeDbaseTags(gxShape theShape);
  21. Boolean CGXtoPostScriptDoesShapeHaveTMode(gxShape aShape);
  22.  
  23. /****
  24.     This method creates a font handler context from the
  25.     font database. 
  26. ****/
  27. void  CGXtoPostScriptTranslator::CreateFontHandler(scalerStreamTypeFlag legalStreamTypes, TFHDownloadFlags flags)
  28. {
  29.     TFontHandlerContext        result = nil;
  30.     OSErr                            status;
  31.  
  32.     /* Save the font handler settings */
  33.     mLegalStreamTypes = legalStreamTypes;
  34.     mFHDownloadFlags = flags;
  35.     
  36.     /* If the database isn't nil, create a font handler. */    
  37.     if (mDbase != nil) {
  38.  
  39.         // FInd out about the product.
  40.         Str255                            version, revision, product;
  41.         status = this->mDevice->GetPSProduct(version, revision, product);
  42.         if (status != noErr)
  43.             throw status;
  44.  
  45.         // Now create a font handler context.            
  46.         status = FontHandlerInit(&mFontHandler, this->mDevice, mDbase, legalStreamTypes, flags, version, revision, product);
  47.         if (status != noErr)     throw status;
  48.             
  49.         status = FontHandlerSetFontVM(mFontHandler, mVMAvailable - kGXtoPSProcSetVM);
  50.         if (status != noErr)     throw status;
  51.             
  52.     }//end if
  53.     
  54. }//CGXtoPostScriptTranslator::CreateFontHandler
  55.  
  56. /********************
  57.  
  58.     This is the constructor for the GX-PS
  59.     Translator.
  60.     
  61.     It allocates the buffers and the PSIE context.
  62.  
  63.     psDevice:                A pointer to a device object which handles the GX PostScript messages.
  64.  
  65.     imageData:            This is the image data handle.  This specifies the capabilities of the target postscript device.
  66.  
  67.     fontDbase:            Nil for draw by draw font management, or a valid font database object.
  68.  
  69.     devMapping:            This is a matrix that maps from 72dpi space to device space.  This matrix will be used to make
  70.                                     device resolution bitmaps for text and transfer modes.
  71.  
  72.     halftoneRecord:        This specifies the default halftone for this job.  If nil, the printers default will be used.
  73.     
  74. *********************/
  75. CGXtoPostScriptTranslator::CGXtoPostScriptTranslator(CGXtoPostScriptDevice* psDevice, gxPostScriptImageDataRec *imageData, 
  76.                                                                                         TFontDbase fontDbase,  gxMapping *devMapping, gxFormatHalftoneInfo *halftoneRecord)
  77. {
  78.     mTransformStack    = nil;
  79.     mTransformCount    = 0;
  80.     mStackAllocation = 0;
  81.     mDbase = fontDbase;
  82.     mFontHandler = nil;
  83.     mVMAvailable = imageData->printerVM;
  84.             
  85.     OSErr        status = noErr;
  86.  
  87.     mDevice = psDevice;
  88.     
  89.     /** Create a font handler context **/
  90.     TFHDownloadFlags            fhFlags = fhNoDownloadFlags;
  91.  
  92.     if (imageData->renderOptions & gxNeedsHexOption)
  93.         fhFlags |= fhDownloadAscii;
  94.  
  95.     if (imageData->languageLevel >= 2)            // Assume for level-2 we can do composite fonts.
  96.         fhFlags |= fhUseTypeZeroFonts;
  97.         
  98.     this->CreateFontHandler(imageData->fontType, fhFlags);
  99.         
  100.     /** Create an Imaging Engine context **/
  101.     status = EnterPostScriptIE(&mPSIEContext, mDevice, imageData, mFontHandler, nil );
  102.     if (status != noErr) throw status;
  103.  
  104.     /* Grab this information for potential transfer mode dealings */
  105.     if (devMapping != nil)
  106.         CopyToMapping(&mDeviceMapping, devMapping);
  107.  
  108.     if (imageData != nil) {
  109.         mDevColorSpace = imageData->devCSpace;
  110.         mDevProfile = imageData->devCProfile;
  111.     }//end if
  112.     
  113.         
  114.     
  115. }//CGXtoPostScriptTranslator
  116.  
  117. /***********
  118.     The destructor cleans up.
  119. ************/
  120. CGXtoPostScriptTranslator::~CGXtoPostScriptTranslator()
  121. {
  122.     if (mTransformStack != nil)
  123.         delete [] mTransformStack;
  124.             
  125.     OSErr status = ExitPostScriptIE(mPSIEContext);
  126.     
  127.     if (mFontHandler != nil) {
  128.         OSErr status2 = FontHandlerShutdown(mFontHandler);
  129.         if (status == noErr) status = status2;
  130.     }//end if
  131.     
  132.     if (status != noErr) throw status;
  133.     
  134. }//~CGXtoPostScriptTranslator
  135.  
  136. /*********
  137.     This method is invoked at the beginning of each page to be rendered.
  138.     
  139.     imageData:        Pointer to an image data record.  Although one was passed to the constructor,
  140.                             We allow the device color profile to be changed on a page by page basis.  That is the only
  141.                             field of the imageData that is used in this call.
  142.     
  143.     devMapping:        Again, we allow this to be changed on a page by page basis.
  144.     halftoneRecord:    This, too on a page by page basis.
  145.     
  146. *********/
  147. void    CGXtoPostScriptTranslator::InitGraphics(gxPostScriptImageDataRec *imageData, gxMapping *devMapping, gxFormatHalftoneInfo *halftoneRecord)
  148. {
  149.     /* Grab this information for potential transfer mode dealings */
  150.     if (devMapping != nil)
  151.         CopyToMapping(&mDeviceMapping, devMapping);
  152.  
  153.     if (imageData != nil) {
  154.         mDevColorSpace = imageData->devCSpace;
  155.         mDevProfile = imageData->devCProfile;
  156.     }//end if
  157.     
  158.     /* Now initialize the graphics state of the imaging engine */
  159.     OSErr        status = PostScriptInitGraphics(mPSIEContext, imageData, devMapping, halftoneRecord);
  160.     if (status != noErr)
  161.         throw status;
  162.             
  163. }//CGXtoPostScriptTranslator::InitGraphics
  164.  
  165.  
  166. /**********
  167.     This method is called to translate a shape to PostScript.
  168.     Typically this is called with a picture for the whole page,
  169.     but this isn't a requirement.
  170. ***********/
  171. void CGXtoPostScriptTranslator::DrawShape(gxShape theShape, Boolean imageTransferModes)
  172. {
  173.     Boolean        pageByPageFonts = (mDbase == nil) ? true : false;
  174.     OSErr        status = noErr;
  175.     gxShape    shapeToDraw = theShape;        
  176.  
  177.     /* Handle fonts if necessary */
  178.     if (pageByPageFonts) {
  179.  
  180.         /* Build a font database for this shape. */
  181.         status = FontDbaseInit(&mDbase, nil);
  182.         nrequire(status, failed_dbaseInit);
  183.         shapeToDraw = CGXToPSBuildShapeDbaseTags(theShape);
  184.         status = FontDbaseAddPage(mDbase, shapeToDraw, false);
  185.         nrequire(status, failed_addPage);
  186.         
  187.         /* Now create a font handler for this shape */
  188.         try {
  189.             this->CreateFontHandler(mLegalStreamTypes, mFHDownloadFlags);
  190.         } catch (OSErr error) {
  191.             status = error;
  192.         }//end try-catch
  193.         nrequire(status, failed_createFH);
  194.         
  195.         /* Now do the font handler doc-level fonts */
  196.         status = mDevice->BufferData("%-- Font Handling: Treating each CGXtoPostScriptTranslator::DrawShape Seperately\r", 81, 0);
  197.         nrequire(status, failed_buff1);
  198.         
  199.         status = FontHandlerDoDocumentHeader(mFontHandler);
  200.         nrequire(status, failed_docHeader);
  201.         
  202.         PostScriptIEReplaceFontHandler(mPSIEContext, mFontHandler);
  203.         
  204.         
  205.     }//end if
  206.  
  207.     /* Draw the shape */
  208.     gxShape tModes = this->InternalDrawShape(shapeToDraw, imageTransferModes);
  209.  
  210.     /* Deal with the transfer modes if necessary */    
  211.     if (tModes != nil) {
  212.         this->RenderTransferModes(theShape, tModes);
  213.         GXDisposeShape(tModes);
  214.     }//end if
  215.         
  216.  
  217. failed_docHeader:
  218. failed_buff1:
  219. failed_doSave:
  220. failed_createFH:
  221. failed_addPage:
  222.  
  223.     /* Deal with font stuff if necessary */
  224.     if (pageByPageFonts) {
  225.         status = FontHandlerShutdown(mFontHandler);
  226.         OSErr saveStatus = FontDbaseShutdown(mDbase, nil);
  227.         if (status == noErr) status = saveStatus;
  228.         mDbase = nil;
  229.         mFontHandler = nil;
  230.  
  231.         if (status == noErr)
  232.             status = mDevice->BufferData("%-- End Font Handling: Treating each CGXtoPostScriptTranslator::DrawShape Seperately\r", 85, 0);
  233.  
  234.     }//end if
  235.     
  236.     if (shapeToDraw != theShape)
  237.         GXDisposeShape(shapeToDraw);
  238.  
  239. failed_dbaseInit:
  240.     if (status != noErr)    throw status;
  241.  
  242. }//CGXtoPostScriptTranslator::DrawShape
  243.  
  244.  
  245. /**********
  246.     This method is invoked after imaging a page.
  247. **********/
  248. void CGXtoPostScriptTranslator::RestoreGraphics(void)
  249. {
  250.     OSErr    status = PostScriptRestoreGraphics(mPSIEContext);
  251.     if (status != noErr)
  252.         throw status;
  253.         
  254. }//CGXtoPostScriptTranslator::RestoreGraphics
  255.  
  256.  
  257. /*****************
  258.  
  259.     Download the required procsets for GX.
  260.     
  261. ******************/
  262. void CGXtoPostScriptTranslator::DownloadProcSets()
  263. {
  264.     OSErr status = PostScriptIEDownloadProcSets(mPSIEContext);
  265.     if (status != noErr)
  266.         throw status;
  267.     
  268.     status = FontHandlerDownloadProcSetList(mDevice);
  269.     if (status != noErr)
  270.         throw status;
  271.  
  272. }//CGXtoPostScriptTranslator::DownloadProcSets
  273.  
  274.  
  275.  
  276. /*****************  Methods for traversing pictures ******************/
  277.  
  278. /****************
  279.     The drawshape method.
  280.     This is invoked for each shape to be drawn.
  281.     If the input shape is a picture, it will be walked recursively using
  282.     the transform stack methods.    
  283.     
  284.     Function result:         A shape is created and returned which contains all the shapes passed in that had transfer modes.
  285.                                         or nil, if the input didn't have any transfer modes.
  286.                                         
  287. ****************/
  288. gxShape CGXtoPostScriptTranslator::InternalDrawShape(gxShape theShape,  Boolean imageTransferModes)
  289. {
  290.     gxShape                result = nil;
  291.     gxShapeType            theType = GXGetShapeType(theShape);
  292.     
  293.     if (theType != gxPictureType) {    
  294.  
  295.         /* Draw the shape.  If it had a transfer mode, return it as the result so it can be accumulated */
  296.  
  297.         if ( imageTransferModes && CGXtoPostScriptDoesShapeHaveTMode(theShape) )
  298.             result = GXCloneShape(theShape);
  299.  
  300.         /* 
  301.             When we are doing transfer modes as an image, we may have to redraw the shape into an offscreen
  302.             in the second pass.  Since the imaging engine tends to be destructive to shapes if it thinks the shape is only used once,
  303.             we clone the shape here to "trick" the imaging engine into making a copy of the shape before
  304.             doing any destructive activities.
  305.         */
  306.         if ( imageTransferModes )
  307.             GXCloneShape(theShape);
  308.             
  309.         OSErr status = PostScriptDrawShape(mPSIEContext, theShape, mTransformStack, mTransformCount);
  310.  
  311.         if ( imageTransferModes )                // clean up our clone if we made one above.
  312.             GXDisposeShape(theShape);
  313.  
  314.         if (status != noErr)
  315.             throw status;
  316.  
  317.  
  318.     } else {
  319.             
  320.         /** Recursively draw each shape in the picture */
  321.         this->PushTransform(GXGetShapeTransform(theShape));
  322.         
  323.         gxTransform        oldTr, overTr;
  324.         gxStyle                oldSt, overSt;
  325.         gxInk                oldInk, overInk;
  326.         gxShape            child;
  327.         long                    count = GXGetPictureParts(theShape, 1, gxSelectToEnd, nil, nil, nil, nil);
  328.  
  329.         // Create a picture to contain any of the shapes that had transfer modes.
  330.         if (imageTransferModes) {
  331.             result = GXNewShape(gxPictureType);
  332.             GXSetShapeTransform(result, GXGetShapeTransform(theShape));
  333.         }//end if
  334.         
  335.         for (long i = 1; i <= count; ++i) {
  336.  
  337.             GXGetPictureParts(theShape, i, 1, &child, &overSt, &overInk, &overTr);
  338.             
  339.             /* Apply the overrides to the child shape*/
  340.             if (overSt) {
  341.                 oldSt = GXCloneStyle(GXGetShapeStyle(child));        // save a reference to the old style
  342.                 GXSetShapeStyle(child, overSt);                            // Apply the overriding style.
  343.             }//end if
  344.             if (overInk) {
  345.                 oldInk = GXCloneInk(GXGetShapeInk(child));            // save a reference to the old ink
  346.                 GXSetShapeInk(child, overInk);                                // Apply the overriding ink.
  347.             }//end if
  348.             if (overTr) {
  349.                 oldTr = GXCloneTransform(GXGetShapeTransform(child));        // save a reference to the old transorm
  350.                 GXSetShapeTransform(child, overTr);                                    // Apply the overriding transform.
  351.             }//end if
  352.  
  353.             // Call draw recursinvely on the child.
  354.             gxShape drawnShape = this->InternalDrawShape(child, imageTransferModes);
  355.  
  356.             /* If the shape we drew had any transfer modes, then add it to the result */
  357.             if (drawnShape != nil) {
  358.                 gxStyle                *pStyle = (overSt != nil) ? &overSt : nil;
  359.                 gxTransform        *pTransform = (overTr != nil) ? &overTr : nil;
  360.                 gxInk                *pInk = (overInk != nil) ? &overInk : nil;
  361.                 GXSetPictureParts(result, 0, 0, 1, &drawnShape, pStyle, pInk, pTransform);
  362.                 GXDisposeShape(drawnShape);            // picture owns it, we don't need it anymore.
  363.             }//end if
  364.             
  365.             
  366.             /* Restore the non-overriding style, ink and transform */
  367.             if (overSt) {
  368.                 GXSetShapeStyle(child, oldSt);
  369.                 GXDisposeStyle(oldSt);
  370.             }//end if
  371.             if (overInk) {
  372.                 GXSetShapeInk(child, oldInk);
  373.                 GXDisposeInk(oldInk);
  374.             }//end if
  375.             if (overTr) {
  376.                 GXSetShapeTransform(child, oldTr);
  377.                 GXDisposeTransform(oldTr);
  378.             }//end if
  379.             
  380.         }//end for
  381.  
  382.         // Return nil if we didn't accumulate any shapes with transfer modes.
  383.         if (imageTransferModes && GXGetPictureParts(result, 1, gxSelectToEnd, nil, nil, nil, nil) == 0) {
  384.             GXDisposeShape(result);
  385.             result = nil;
  386.         }//end if
  387.         
  388.         this->PopTransform();
  389.         
  390.     }//end if
  391.     
  392.     return result;
  393.     
  394. }//CGXtoPostScriptTranslator::InternalDrawShape
  395.  
  396.  
  397. /**********
  398.     This method pushes a picture transform on the stack.
  399. **********/
  400. void        CGXtoPostScriptTranslator::PushTransform(gxTransform tr)
  401. {
  402.     if (mTransformCount + 1 > mStackAllocation) {
  403.         
  404.         /* Allocate a new list and copy old list in */
  405.         gxTransform            *newStack = new gxTransform[mStackAllocation + 10];                // grow list by 10 each time.
  406.         
  407.         mStackAllocation += 10;
  408.         if (mTransformCount > 0)
  409.             ::BlockMoveData(mTransformStack, newStack, mTransformCount * sizeof(gxTransform));
  410.  
  411.         
  412.         // Now the stack is the new list.        
  413.         delete [] mTransformStack;
  414.         mTransformStack = newStack;
  415.                 
  416.     }//end if
  417.             
  418.     /* Now put the new transform on the stack */
  419.     mTransformStack[mTransformCount] = GXCloneTransform(tr);                // clone it so that the stack is an ownder.
  420.     mTransformCount += 1;
  421.         
  422. }//CGXtoPostScriptTranslator::PushTransform
  423.  
  424. /*************
  425.     This methods pops a picture transform off the stack.
  426.         Note, we never reduce the size of the allocated stack, not worth the trouble.
  427. **************/
  428. void        CGXtoPostScriptTranslator::PopTransform()
  429. {
  430.     if (mTransformCount <= 0)
  431.         throw -999;
  432.  
  433.     GXDisposeTransform(mTransformStack[mTransformCount - 1]);        // we don't own it anymore.
  434.     mTransformCount -= 1;
  435.  
  436. }//CGXtoPostScriptTranslator::PopTransform
  437.  
  438.  
  439.  
  440. /*******************************************************
  441.  
  442.     CGXBuildShapeDbaseTags:
  443.     
  444.     Routine to build font database tags on a shape.
  445.     
  446.     Routine builds font database tags on a shape by 
  447.     flattening it.  The actual flattened information
  448.     is ignored.  We only want to get the tags built.
  449.     
  450.     Routine returns a picture that has the database tags
  451.     on it.  This is because flattening does not generate
  452.     the font database on normal shapes, just pictures.
  453.     
  454.     The picture is newly created and must therefore be disposed
  455.     of by the client of this call.
  456.     
  457. *********************************************************/
  458. static long dbaseSpoolProc(gxSpoolCommand command, struct gxSpoolBlock *block);
  459. static long dbaseSpoolProc(gxSpoolCommand command, struct gxSpoolBlock *block)
  460.     {
  461.     #pragma unused (command, block)
  462.         /** do nothing **/
  463.         return(0);
  464.     }
  465.  
  466. gxShape CGXToPSBuildShapeDbaseTags(gxShape theShape)
  467.     {
  468.         gxSpoolBlock             theSpool;
  469.         char                            dummyBuffer[50];                // a place for graphics to stick data.
  470.         gxShape                    thePict;
  471.         
  472.         thePict = GXNewShape(gxPictureType);
  473.         GXSetPictureParts(thePict, 0, 0, 1, &theShape, nil, nil, nil);
  474.         
  475.         theSpool.spoolProcedure = NewgxSpoolProc(dbaseSpoolProc);
  476.         theSpool.buffer = dummyBuffer;
  477.         theSpool.bufferSize = 50;
  478.         
  479.         GXFlattenShape(thePict, gxFontListFlatten + gxFontGlyphsFlatten + gxFontVariationsFlatten, &theSpool);
  480.         
  481.         DisposeRoutineDescriptor(theSpool.spoolProcedure);
  482.         
  483.         return(thePict);
  484.     
  485.     }//FHBuildShapeDbaseTags
  486.  
  487. /*************************************** TRANSFER MODE UITILITIES ***********************************/
  488.  
  489. Boolean CGXtoPostScriptDoesShapeHaveTMode(gxShape aShape)
  490. {
  491.     Boolean                result = true;
  492.     gxInk                theInk = GXGetShapeInk(aShape);
  493.  
  494.     if (TMTestCopyMode(theInk))
  495.         result = false;
  496.     else if (TMTestOrMode(theInk)) {                    // or mode 1-bit bitmaps can be handled by the imaging engine using the "imagemask" postscript operator.
  497.  
  498.         if (GXGetShapeType(aShape) == gxBitmapType) {
  499.             gxBitmap        bits;
  500.             GXGetBitmap(aShape, &bits, nil);
  501.             if (bits.pixelSize == 1)
  502.                 result = false;
  503.         }//end if
  504.  
  505.     }//end if
  506.     
  507.     return result;
  508. }
  509.  
  510.  
  511.  
  512.  
  513. /************************* DEFAULT IMPLEMENTATION OF THE POSTSCRIPT DEVICE OBJECT *************************/
  514.  
  515. #include <StdIo.h>
  516. #include <String.h>
  517. #include <GXExceptions.h>
  518.  
  519. /********
  520.     Default status message uses printf.
  521. *********/
  522. OSErr CGXtoPostScriptDevice::ReportStatus(long count, unsigned char message[])
  523. {
  524.     for (int i = 0; i < count; ++i)
  525.         printf("%c", message[i]);
  526.     printf("\n");
  527.     return noErr;
  528. };
  529.  
  530. /*******
  531.     This function sends a status message showing
  532.     what font is being downloaded.  
  533.         Note:        This function could be localized better than this.
  534. ********/
  535. OSErr CGXtoPSReportFontDownload(CGXtoPostScriptDevice *dev, gxFont theFont);
  536. OSErr CGXtoPSReportFontDownload(CGXtoPostScriptDevice *dev, gxFont theFont)
  537. {
  538.     OSErr                        status = noErr;
  539.     unsigned char            *name;
  540.     long                            nameLen;
  541.  
  542.     nameLen = GXFindFontName(theFont, gxFullFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil);
  543.     if (nameLen > 0) {
  544.         name = new unsigned char[nameLen + 18];
  545.         memcpy(name, "Downloading font: ", 18);
  546.         GXFindFontName(theFont, gxFullFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, name + 18, nil);
  547.         status = dev->ReportStatus(nameLen + 18, name);
  548.         delete [] name;
  549.     }//end if
  550.     return(status);
  551. }
  552.  
  553.  
  554.  
  555. /**
  556.     Extended spool block for our font streaming.
  557.     This allows our callback to be handed some extra
  558.     useful data such as:
  559. **/
  560. typedef struct {
  561.     gxSpoolBlock                            gxBlock;                // the first field is the gxBlock, so the pointer can be used by GX internally.
  562.     CGXtoPostScriptDevice            *psDevice;            // A pointer to the device object so we can send messages.
  563.     OSErr                                    status;                    // A place to store errors
  564.     Boolean                                    canIdle;                    // This tells us if we can idel during the download process.
  565. } TGXToPSSpoolBlock;
  566.     
  567. static long BufferFont( gxSpoolCommand command, gxSpoolBlock *block );
  568. static long BufferFont( gxSpoolCommand command, gxSpoolBlock *block )
  569. {
  570.     TGXToPSSpoolBlock        *realBlock = (TGXToPSSpoolBlock*)block;
  571.     realBlock->status = noErr;
  572.     if ( command == gxWriteSpool ) {
  573.  
  574.         realBlock->status = realBlock->psDevice->BufferData((char*)(block->buffer), block->count, 0);            // send the font data to the printer.
  575.         nrequire(realBlock->status, failed_send);
  576.  
  577.         if (realBlock->canIdle)        // give up time if the scaler was reentrent.
  578.             realBlock->status = realBlock->psDevice->Idle();
  579.                 
  580.     }//end if
  581.     
  582. failed_send:
  583.     return(realBlock->status);
  584.     
  585. }//BufferFont
  586.  
  587.  
  588. /***************************
  589.     The default implementation of the stream font message.
  590.     
  591.     This method will use GXFlattenFont to pipe font data through
  592.     the BufferData message of the device object.
  593. ****************************/
  594. OSErr CGXtoPostScriptDevice::StreamFont(gxFont whatFont, scalerStream *streamRecord)
  595. {
  596.     OSErr                        status;
  597.     Boolean                        streamaction;
  598.     Boolean                        reentrant;
  599.     TGXToPSSpoolBlock    block;
  600.  
  601.     nrequire( status = this->Idle(), JobIdleFailed );                    // Idle at least once per call.
  602.  
  603.     /*
  604.         If we are downloding a font, check to see if there is reentrancy in the scaler, and display a status
  605.         message saying what font we are downloading
  606.     */
  607.     if( ( streamaction = ( (streamRecord->action == downloadStreamAction)  || (streamRecord->action == asciiDownloadStreamAction) ) ) ) {
  608.             nrequire( status = CGXtoPSReportFontDownload( this, whatFont ), ReportStatusFailed );
  609.             // disable callouts for non-reentrant scalers when downloading.
  610.             reentrant = GXisScalerStreamingReentrant( GXGetFontFormat( whatFont ) );                // see if we can idle during the download.
  611.     }//end if
  612.  
  613.     block.gxBlock.spoolProcedure = NewgxSpoolProc(BufferFont);                // Use our buffer proc.
  614.     block.gxBlock.buffer = nil;
  615.     block.gxBlock.bufferSize = 0;
  616.     block.psDevice = this;
  617.     block.canIdle = reentrant;
  618.     
  619.     GXFlattenFont( whatFont, streamRecord, (gxSpoolBlock*)&block );
  620.     
  621.     DisposeRoutineDescriptor(block.gxBlock.spoolProcedure);
  622.     
  623.  
  624. ReportStatusFailed:
  625. JobIdleFailed:    
  626.     return( status );
  627.  
  628. }//CGXtoPostScriptDevice::StreamFont
  629.  
  630.  
  631. /*************
  632.     The default implementation of the printer-glyphs message.
  633.     In the default implmenatation, we'll say that none of the glyphs
  634.     for the font are available.
  635. **************/
  636. OSErr CGXtoPostScriptDevice::GetPrinterGlyphsInformation(gxPrinterGlyphsRec *printerGlyphs)
  637. {
  638.     OSErr        status = noErr;
  639.     
  640.     printerGlyphs->platform = gxGlyphPlatform;
  641.     unsigned long        *glyphBits = &(printerGlyphs->glyphBits[0]);
  642.     long                     lwCount = ((printerGlyphs->nGlyphs + 31) / 32);
  643.  
  644.     for (int i = 0; i < lwCount; ++i)            // by clearing all of the bits, we signal the font handler to download all glyphs.
  645.         glyphBits[i] = 0;
  646.         
  647.     return(status);
  648.  
  649. }//CGXtoPostScriptDevice::GetPrinterGlyphsInformation
  650.  
  651.  
  652. /********
  653.     The default product method
  654.     returns *'s for all 3 names.
  655. *********/
  656. OSErr CGXtoPostScriptDevice::GetPSProduct(Str255 version, Str255 revision, Str255 product)
  657. {
  658.     version[0] = 1;
  659.     version[1] = '*';
  660.  
  661.     revision[0] = 1;
  662.     revision[1] = '*';
  663.     
  664.     product[0] = 1;
  665.     product[1] = '*';
  666.  
  667.     return noErr;
  668. }
  669.  
  670.